deps(actions): bump actions/setup-node from 4 to 6#7
Conversation
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 6. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](actions/setup-node@v4...v6) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
LabelsThe following labels could not be found: Please fix the above issues or remove invalid values from |
|
Fechando: o Dependabot lê |
|
OK, I won't notify you again about this release, but will get in touch when a new version is available. If you'd rather skip all updates until the next major or minor version, let me know by commenting If you change your mind, just re-open this PR and I'll resolve any conflicts on it. |
…1.7] [DESIGN-v3]
Implementa o coração da busca. SearchService.query(QuerySpec) ->
SearchResultPage com TODAS as 12 invariantes do algorithms specialist
(_specialist-outputs/02-algorithms-architect.md §8).
apps/search/services.py:
Fluxo (algorithms §7):
1. Decode cursor (Inv 5) — InvalidCursorError propaga p/ view = 400
2. normalize_search_text (Inv 2) — simétrico com signal
3. Validate token cap (Inv 8) — TooManyTokensError = 400
4. Empty-tsquery early-exit (Inv 7) — 0 hits Postgres em q='!!!' ou
q='o de da' (stopwords-only)
5. Bifurca por vendor:
- SQLite-dev (ADR-020): __icontains via Article queryset com
status='published' filter (Inv 4) e ORDER BY published_at, id
(Inv 1 determinismo)
- Postgres: CTE candidates LIMIT 500 (M1) + scored com
ROUND(score::numeric, 6) (Inv 6) + cursor tuple comparison +
ORDER BY (score DESC, published_at DESC, article_id ASC)
6. SET LOCAL statement_timeout='500ms' (Inv 12 — defesa T30.4.X9
independente do role)
7. plainto_tsquery (Inv 3) — NUNCA to_tsquery
8. ts_lexize('portuguese_stem', ...) por token via unnest
-> query_terms_expanded (Inv 11)
9. EXPLAIN (FORMAT JSON) -> Plan Rows + estimate_total floor (ADR-025)
10. Side-fetch Article in_bulk (anti N+1) preservando ordem do ranking
11. Encode next_cursor com depth=page_count (Inv 9 enforced no decode)
Public helpers:
- estimate_total(results_len, per_page, plan_rows, page_count)
Floor = max(plan_rows, (page-1)*per_page + results_len). ADR-025
garante que estimate nunca seja menor que evidência empírica.
- TooManyTokensError — view traduz p/ 400 query_too_complex
- _PT_BR_STOPWORDS frozenset (mínimo cobre adversarial input típico)
- _significant_tokens(), _is_empty_tsquery() — Inv #7 helpers
Comment-locks anti-regressão:
- SECURITY M-01: queries SEMPRE com parametrização cursor.execute(sql,
params) ou QuerySet .filter. NUNCA .extra(where=) ou raw().
- ADR-037: response function-pure de (q, filters, cursor); NÃO adicionar
campos por-usuário sem rever (H-04 cross-tier leak).
test_service.py: 11 testes
- estimate_total: max(plan, floor) com underestimate
- empty q early-exit via CaptureQueriesContext (0 queries)
- query_terms_expanded é tuple
- SQLite fallback exercitado (rota __icontains)
- InvalidCursorError propaga (cursor='garbage')
- TooManyTokensError em 9 tokens (cap 8)
- Postgres-only: plainto_tsquery sanitiza, statement_timeout aplicado
(skipped em SQLite-dev via marker requires_postgres)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Fecha o endpoint /api/v1/search/articles/ — Fase 2 backend leitura completa. Tasks: T30.1.8, T30.1.9, T30.1.X4 (feature flag), T30.4.X4 (cache key sha256+auth_tier). apps/search/serializers.py: - SearchQuerySerializer: valida query string -> QuerySpec (frozen DTO). Whitelist H-01: q deve casar ^[a-zA-Z0-9À-ſ\s\-]+$ (rejeita HTML chars ANTES de bater no DB). 2 ≤ len ≤ 200. per_page ≤ 50. validate() cruza de ≤ ate. to_query_spec() materializa DTO. - SearchResultItemSerializer + SearchResultPageSerializer: projeção JSON do response shape ADR-023 (id, title, slug, excerpt, published_at, author, category, cover_url, score, query_terms_expanded, took_ms). apps/search/views.py — SearchArticlesView (APIView, GET only, AllowAny): 1. Feature flag T30.1.X4: SEARCH_FEATURE_ENABLED=False -> 503 + Retry-After: 60 (cutover deliberado em prod). 2. SearchQuerySerializer.is_valid() -> 400 com erros estruturados. 3. Cache HIT/MISS via build_cache_key(spec, auth_tier) — H-04 ADR-037 garante isolamento anon vs user. 4. Service: InvalidCursorError -> 400 cursor_invalid (Inv #5); TooManyTokensError -> 400 query_too_complex (Inv #8). 5. Headers: Cache-Control public/max-age=60/swr=300, Vary: Authorization+ Accept-Encoding (separa CDN entre tiers), X-Robots-Tag noindex (T30.4.X11/L-05), X-Cache HIT|MISS. - Throttles: SearchAnonThrottle (30/min IP) + SearchUserThrottle (60/min user) + SearchGlobalThrottle (500/min global, defesa H-03 botnet). apps/search/urls.py + config/urls.py: - path('api/v1/search/', include('apps.search.urls')) - path('articles/', SearchArticlesView.as_view(), name='articles') Extensível: /search/comments/, /search/suggest/ futuros. Comment-locks anti-regressão: response function-pure de (q, filters, cursor) — NÃO adicionar campos por-usuário sem rever ADR-037 (H-04 cross-tier leak). test_views.py: 16 testes via DRF APIClient cobrindo: - Feature flag 503 + Retry-After - Validação serializer (q missing/short/long/HTML chars, per_page > 50, date range invertido) -> 400 - Cursor inválido -> 400 cursor_invalid (Inv #5) - 9 tokens -> 400 query_too_complex (Inv #8) - 200 OK happy path com response shape completo (Inv #11 honrado) - Stopwords-only -> 200 results=[] (Inv #7 early-exit) - Headers Cache-Control + Vary (H-04 CDN) + X-Robots-Tag (T30.4.X11) - Cache MISS -> HIT (segundo request bate em cache) - H-04 critical: anon e user com MESMA query produzem cache keys DIFERENTES (anon MISS-HIT-HIT; user MISS na própria chave separada) Smoke manual: - SEARCH_FEATURE_ENABLED=True + GET q=kpop -> 200 OK com headers OK - SEARCH_FEATURE_ENABLED=False + GET q=kpop -> 503 + Retry-After: 60 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bumps actions/setup-node from 4 to 6.
Release notes
Sourced from actions/setup-node's releases.
... (truncated)
Commits
48b55a0Update Node.js versions in versions.yml and bump package to v6.4.0 (#1533)ab72c7eUpgrade@actionsdependencies (#1525)53b8394Bump minimatch from 3.1.2 to 3.1.5 (#1498)54045abScope test lockfiles by package manager and update cache tests (#1495)c882bffReplace uuid with crypto.randomUUID() (#1378)774c1d6feat(node-version-file): support parsingdevEnginesfield (#1283)efcb663fix: remove hardcoded bearer (#1467)d02c89dFix npm audit issues (#1491)6044e13Docs: bump actions/checkout from v5 to v6 (#1468)8e49463Fix README typo (#1226)Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)